﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;

namespace DM_SSSDBM
{
    public partial class Form1 : Form
    {
        public SqlConnection MainSQLCon= new SqlConnection();

        public Form1()
        {
            InitializeComponent();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (Connect() == 1)
            {
                RefreshData();
                toolStripButton2.Enabled = true;
                toolStripButton3.Enabled = true;
                toolStripButton4.Enabled = true;
                toolStripButton5.Enabled = true;
                toolStripButton6.Enabled = true;
                toolStripButton7.Enabled = true;
            }

        }

        private int Connect()
        {
            int rtn = 0;
            {
                ServerLogin l = new ServerLogin();
                l.ShowDialog();                
                if (l.ConStat)
                {
                    rtn = 1;
                    
                    MainSQLCon = l.MainSQLCon;
                }
            }
            return rtn;
        }

        private void RefreshData()
        {
            treeView1.Nodes.Clear();
            Microsoft.SqlServer.Management.Common.ServerConnection srvCon = new Microsoft.SqlServer.Management.Common.ServerConnection(MainSQLCon);
            Microsoft.SqlServer.Management.Smo.Server SourceServer = new Server(srvCon);
            {
                TreeNode serverLevel = new TreeNode(SourceServer.Name);
                /*Server Info builder*/
                {
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server Name: " + SourceServer.Name) + Environment.NewLine;
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server Version: " + SourceServer.VersionString) + Environment.NewLine;
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server Edition: " + SourceServer.Edition) + Environment.NewLine;
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server EngineEdition: " + SourceServer.EngineEdition) + Environment.NewLine;
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server OSVersion: " + SourceServer.OSVersion) + Environment.NewLine;
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server State: " + SourceServer.State) + Environment.NewLine;
                    serverLevel.ToolTipText = serverLevel.ToolTipText + ("Server Status: " + SourceServer.Status) + Environment.NewLine;
                   
                
                }
                foreach (Database db in SourceServer.Databases)
                {
                    if ((!db.IsDatabaseSnapshot) && (!db.IsSystemObject))
                    {
                        TreeNode Database = new TreeNode(db.Name); /*Set new object & gives a name*/
                        Database.ImageIndex = 1; /*Sets an Image*/
                        Database.ContextMenuStrip = DatabaseContexmenu;
                        Database.ToolTipText = "";
                        /*Database Info builder*/
                        {
                            Database.ToolTipText = Database.ToolTipText + ("DB Name: " + db.Name) + Environment.NewLine;
                            Database.ToolTipText = Database.ToolTipText + ("Creation date: " + db.CreateDate) + Environment.NewLine;
                            Database.ToolTipText = Database.ToolTipText + ("DB Owner: " + db.Owner) + Environment.NewLine;
                            Database.ToolTipText = Database.ToolTipText + ("DB size: " + db.Size) + Environment.NewLine;
                        }
                        foreach (Database dbSS in SourceServer.Databases)
                        {
                            if ((dbSS.IsDatabaseSnapshot) && (dbSS.DatabaseSnapshotBaseName == db.Name))
                            {
                                TreeNode DatabaseSS = new TreeNode(dbSS.Name);
                                DatabaseSS.ContextMenuStrip = SnapshotContextmenu;
                                /*Snapshot Info builder*/
                                {
                                    DatabaseSS.ToolTipText = DatabaseSS.ToolTipText + ("DB Name: " + dbSS.Name) + Environment.NewLine;
                                    DatabaseSS.ToolTipText = DatabaseSS.ToolTipText + ("Database Snapshot Base: " + dbSS.DatabaseSnapshotBaseName) + Environment.NewLine;
                                    DatabaseSS.ToolTipText = DatabaseSS.ToolTipText + ("Creation date: " + dbSS.CreateDate) + Environment.NewLine;
                                    DatabaseSS.ToolTipText = DatabaseSS.ToolTipText + ("DB Owner: " + dbSS.Owner) + Environment.NewLine;
                                    DatabaseSS.ToolTipText = DatabaseSS.ToolTipText + ("DB size: " + dbSS.Size) + Environment.NewLine;
                                }
                                DatabaseSS.ImageIndex = 2;
                                Database.Nodes.Add(DatabaseSS);
                            }
                        }
                        
                        serverLevel.Nodes.Add(Database);
                        
                    }
                }
                serverLevel.Expand();
                treeView1.Nodes.Add(serverLevel);
                /*Add the SS DB*/
            }
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            treeView1.SelectedImageIndex = treeView1.SelectedNode.ImageIndex;

        }

        private void treeView1_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                MessageBox.Show(treeView1.SelectedNode.ToolTipText, "DB Information for " + treeView1.SelectedNode.Text);
            }
            catch (Exception ex) { }
        }

        private void infoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                MessageBox.Show(treeView1.SelectedNode.ToolTipText, "DB Information for " + treeView1.SelectedNode.Text);
            }
            catch (Exception ex) { }
        }

        private void infoToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                MessageBox.Show(treeView1.SelectedNode.ToolTipText, "DB Information for " + treeView1.SelectedNode.Text);
            }
            catch (Exception ex) { }
        }

        private void dropSnapshotToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Drop_Snapshot(treeView1.SelectedNode.Text);
            }
            catch (Exception ex) { }
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            RefreshData();
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            try
            {
                Drop_Snapshot(treeView1.SelectedNode.Text);
            }
            catch (Exception ex) { }
        }

        private void toolStripButton7_Click(object sender, EventArgs e)
        {
            try
            {
                MessageBox.Show(treeView1.SelectedNode.ToolTipText, "DB Information for " + treeView1.SelectedNode.Text);
            }
            catch (Exception ex) { }
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            try
            {
                if (treeView1.SelectedNode.ImageIndex == 1)
                {
                    create_Snapshoot(treeView1.SelectedNode.Text);
                }
            }
            catch (Exception ex)
            { }
        }


        private void create_Snapshoot(string DBNAME)
        { 
            
            try
            {
               
                DateTime time = DateTime.Now;              // Use current time
                string format = "yyyyMMdd";    // Use this format
                string ssname = DBNAME + "_SS" + "_" + time.ToString(format);

                if (InputBox("Create snapshot for "+DBNAME+" ", "Dnapshot name:", ref ssname) == DialogResult.OK)
                {
                  
                }
                else
                {
                    return;

                }

                Microsoft.SqlServer.Management.Common.ServerConnection srvCon = new Microsoft.SqlServer.Management.Common.ServerConnection(MainSQLCon);
                Server SourceServer = new Server(srvCon);
                
                foreach (Database DB in SourceServer.Databases)
                {
                    if (DB.Name == ssname)
                    {
                        MessageBox.Show("snapshot Failed, Snapshot to db " + DBNAME + ", named ," + ssname + " already exist..");
                        return;
                    }
                }

                Database sourceDB = SourceServer.Databases[(DBNAME)];
                Database snapshot = new Database(SourceServer, ssname);

                snapshot.DatabaseSnapshotBaseName = sourceDB.Name;
                foreach (FileGroup fg in sourceDB.FileGroups)
                {

                    snapshot.FileGroups.Add(new FileGroup(snapshot, fg.Name));

                }
                foreach (FileGroup fg in sourceDB.FileGroups)
                {

                    foreach (DataFile df in fg.Files)
                    {
                        string dest_path = sourceDB.PrimaryFilePath + "\\" + df.Name + "_" + ssname + ".ss";
                        snapshot.FileGroups[fg.Name].Files.Add(new DataFile(snapshot.FileGroups[fg.Name], df.Name, dest_path));
                    }

                }

                snapshot.Create();
                MessageBox.Show("snapshot " + ssname + " was created for DB" + DBNAME);
                RefreshData();
            }
            catch (SmoException smoex)
            {
                
                Exception ex;
                ex = smoex.InnerException;
                string error = "";
                error = error +"snapshot Failed...:" + Environment.NewLine;
                while (!object.ReferenceEquals(ex.InnerException, (null)))
                {
                    error = error + " >" + ex.InnerException.Message + Environment.NewLine;
                    ex = ex.InnerException;
                }
                MessageBox.Show(error);
            }
            catch (Exception ex)
            {
                Exception exx;
                exx = ex.InnerException;
                string error = "";
                error = error + "snapshot Failed...:" + Environment.NewLine;
                while (!object.ReferenceEquals(ex.InnerException, (null)))
                {
                    error = error + " >" + ex.InnerException.Message + Environment.NewLine;
                    ex = ex.InnerException;
                }
                MessageBox.Show(error);
            }
        }

        private void Drop_Snapshot(string DBname)
        {
            if (MessageBox.Show("Are you sure to drop Database " + DBname + " ?", "", MessageBoxButtons.YesNoCancel) == System.Windows.Forms.DialogResult.Yes)
            {
                try
                {
                    Microsoft.SqlServer.Management.Common.ServerConnection srvCon = new Microsoft.SqlServer.Management.Common.ServerConnection(MainSQLCon);
                    Microsoft.SqlServer.Management.Smo.Server SourceServer = new Server(srvCon);
                    /*Verify that is not A regular DB*/
                    if (SourceServer.Databases[DBname].IsDatabaseSnapshot)
                    {
                        SourceServer.Databases[DBname].Drop();
                        MessageBox.Show("selected database snapshot droped");
                        RefreshData();
                    }
                    else
                    {
                        MessageBox.Show("Cannot drop selected database, selectedd db is not a snapshot");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Cannot drop selected database" + ex.Message);
                }
            }
        }


        public static DialogResult InputBox(string title, string promptText, ref string value)
        {
            Form form = new Form();
            Label label = new Label();
            TextBox textBox = new TextBox();
            Button buttonOk = new Button();
            Button buttonCancel = new Button();

            form.Text = title;
            label.Text = promptText;
            textBox.Text = value;

            buttonOk.Text = "OK";
            buttonCancel.Text = "Cancel";
            buttonOk.DialogResult = DialogResult.OK;
            buttonCancel.DialogResult = DialogResult.Cancel;

            label.SetBounds(9, 20, 372, 13);
            textBox.SetBounds(12, 36, 372, 20);
            buttonOk.SetBounds(228, 72, 75, 23);
            buttonCancel.SetBounds(309, 72, 75, 23);

            label.AutoSize = true;
            textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
            buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

            form.ClientSize = new Size(396, 107);
            form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
            form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
            form.FormBorderStyle = FormBorderStyle.FixedDialog;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.MinimizeBox = false;
            form.MaximizeBox = false;
            form.AcceptButton = buttonOk;
            form.CancelButton = buttonCancel;

            DialogResult dialogResult = form.ShowDialog();
            value = textBox.Text;
            return dialogResult;
        }

        private void craeteSnapshotToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (treeView1.SelectedNode.ImageIndex == 1)
                {
                    create_Snapshoot(treeView1.SelectedNode.Text);
                }
            }
            catch (Exception ex)
            { }
        }

        private void RestoreFromSnapshot(string DBNAME,string SS_DB)
        {
            try
            {
                Microsoft.SqlServer.Management.Common.ServerConnection srvCon = new Microsoft.SqlServer.Management.Common.ServerConnection(MainSQLCon);
                Server SourceServer = new Server(srvCon);
                Database SNP_DRP = SourceServer.Databases[SS_DB];

                if ((!SourceServer.Databases[SS_DB].IsDatabaseSnapshot)||(!(SourceServer.Databases[SS_DB].DatabaseSnapshotBaseName == DBNAME)))
                {
                   MessageBox.Show("Restore from SS failed, DB not marked as has snapshots");
                   return;
                }

                int i = 0;
                foreach (Database db in SourceServer.Databases)
                {
                    if (db.DatabaseSnapshotBaseName == DBNAME) i = i + 1;
                }
                if (i > 1)
                {
                    MessageBox.Show("Restore from SS failed, Drop all other DB in order to restore");
                    return;
                }

                string ResString = "Use master;ALTER DATABASE " + DBNAME + " SET SINGLE_USER WITH ROLLBACK IMMEDIATE; restore database " + DBNAME + " from database_snapshot = '" + SS_DB + "' ;ALTER DATABASE " + DBNAME + " SET MULTI_USER WITH ROLLBACK IMMEDIATE";
                textBox1.Text = ResString;
                SourceServer.ConnectionContext.ExecuteNonQuery(ResString);
               MessageBox.Show("restore" + DBNAME + " from snapshot "+SS_DB+ "Finished...");
                
            }
            catch (SmoException smoex)
            {
                Console.WriteLine(smoex.Message);
                Exception ex;
                ex = smoex.InnerException;
                string error = "snapshot restore Failed...";
                
                while (!object.ReferenceEquals(ex.InnerException, (null)))
                {
                    Console.WriteLine(" >" + ex.InnerException.Message);
                    error=error + " >" + ex.InnerException.Message;
                    ex = ex.InnerException;
                }
                MessageBox.Show(error);
            }
            catch (Exception smoex)
            {
                Console.WriteLine(smoex.Message);
                Exception ex;
                ex = smoex.InnerException;
                string error = "snapshot restore Failed..." + smoex.Message +ex.Message;
                
                while (!object.ReferenceEquals(ex.InnerException, (null)))
                {
                    Console.WriteLine(" >" + ex.InnerException.Message);
                    error = error + " >" + ex.InnerException.Message;
                    ex = ex.InnerException;
                }
                MessageBox.Show(error);
            }
        }


        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            try
            {
                /*Verify selected ss*/
                if (treeView1.SelectedNode.ImageIndex == 2)
                {
                    RestoreFromSnapshot(treeView1.SelectedNode.Parent.Text, treeView1.SelectedNode.Text);
                }
            }
            catch (Exception ex) { }
        }

        private void restoreDBFromThisSnapshotToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                /*Verify selected ss*/
                if (treeView1.SelectedNode.ImageIndex == 2)
                {
                    RestoreFromSnapshot(treeView1.SelectedNode.Parent.Text, treeView1.SelectedNode.Text);
                }
            }
            catch (Exception ex) { }
        }
    }
}
